//
// Created by 29108 on 2025/7/15.
//

#ifndef LOAD_BALANCER_H
#define LOAD_BALANCER_H

#include <string>
#include <chrono>
#include <map>
#include <vector>
#include <optional>
#include <mutex>

namespace core_services {
    namespace api_gateway {

        /**
         * @brief 负载均衡器类 - 实现多种负载均衡策略
         * @details 支持轮询、加权轮询、最少连接数三种负载均衡算法
         *
         * 核心功能：
         * - 服务实例管理（添加、删除、健康检查）
         * - 多种负载均衡策略
         * - 线程安全的实例选择
         * - 连接数统计和监控
         */
        class LoadBalancer {
        public:
            /**
             * @brief 负载均衡策略枚举
             */
            enum class Strategy {
                ROUND_ROBIN,           ///< 轮询策略
                WEIGHTED_ROUND_ROBIN,  ///< 加权轮询策略
                LEAST_CONNECTIONS      ///< 最少连接数策略
            };

            /**
             * @brief 服务实例结构体
             */
            struct ServiceInstance {
                std::string host;                                    ///< 主机地址
                int port;                                           ///< 端口号
                int weight = 1;                                     ///< 权重（用于加权轮询）
                bool healthy = true;                                ///< 健康状态
                std::chrono::system_clock::time_point last_check;  ///< 最后检查时间
            };

            /**
             * @brief 构造函数
             * @param strategy 负载均衡策略，默认为轮询
             */
            explicit LoadBalancer(Strategy strategy = Strategy::ROUND_ROBIN);

            /**
             * @brief 析构函数
             */
            ~LoadBalancer() = default;

            // ==================== 服务实例管理 ====================

            /**
             * @brief 添加服务实例
             * @param service_name 服务名称
             * @param instance 服务实例信息
             * @details 将新的服务实例添加到指定服务的实例列表中
             */
            void addInstance(const std::string& service_name, const ServiceInstance& instance);

            /**
             * @brief 移除服务实例
             * @param service_name 服务名称
             * @param instance_id 实例标识符（格式：host:port）
             * @details 从指定服务的实例列表中移除实例
             */
            void removeInstance(const std::string& service_name, const std::string& instance_id);

            /**
             * @brief 清除服务的所有实例
             * @param service_name 服务名称
             * @details 清除指定服务的所有实例
             */
            void clearServiceInstances(const std::string& service_name);

            /**
             * @brief 添加服务实例（别名方法）
             * @param service_name 服务名称
             * @param instance 服务实例
             * @details addInstance的别名方法，用于兼容性
             */
            void addServiceInstance(const std::string& service_name, const ServiceInstance& instance);

            /**
             * @brief 更新服务实例健康状态
             * @param service_name 服务名称
             * @param instance_id 实例标识符
             * @param healthy 健康状态
             * @details 更新指定服务实例的健康状态，影响负载均衡选择
             */
            void updateInstanceHealth(const std::string& service_name, const std::string& instance_id, bool healthy);

            // ==================== 负载均衡选择 ====================

            /**
             * @brief 选择服务实例
             * @param service_name 服务名称
             * @return 选中的服务实例，如果没有可用实例则返回空
             * @details 根据配置的负载均衡策略选择最合适的服务实例
             */
            std::optional<ServiceInstance> selectInstance(const std::string& service_name);

            // ==================== 连接管理 ====================

            /**
             * @brief 增加实例连接数
             * @param service_name 服务名称
             * @param instance_id 实例标识符
             * @details 用于最少连接数策略的连接计数
             */
            void incrementConnections(const std::string& service_name, const std::string& instance_id);

            /**
             * @brief 减少实例连接数
             * @param service_name 服务名称
             * @param instance_id 实例标识符
             * @details 用于最少连接数策略的连接计数
             */
            void decrementConnections(const std::string& service_name, const std::string& instance_id);

            // ==================== 状态查询 ====================

            /**
             * @brief 获取当前负载均衡策略
             * @return 当前策略
             */
            Strategy getStrategy() const;

            /**
             * @brief 获取服务的所有实例
             * @param service_name 服务名称
             * @return 服务实例列表
             */
            std::vector<ServiceInstance> getInstances(const std::string& service_name) const;

            /**
             * @brief 获取服务的健康实例数量
             * @param service_name 服务名称
             * @return 健康实例数量
             */
            size_t getHealthyInstanceCount(const std::string& service_name) const;

        private:
            Strategy strategy_;                                                    ///< 负载均衡策略
            std::map<std::string, std::vector<ServiceInstance>> service_instances_; ///< 服务实例映射
            std::map<std::string, size_t> round_robin_index_;                      ///< 轮询索引
            std::map<std::string, std::map<std::string, size_t>> connection_counts_; ///< 连接数统计
            mutable std::mutex instances_mutex_;                                   ///< 实例访问锁

            // ==================== 私有方法 ====================

            /**
             * @brief 轮询策略选择实例
             * @param service_name 服务名称
             * @param instances 健康实例列表
             * @return 选中的实例
             */
            std::optional<ServiceInstance> selectRoundRobin(
                const std::string& service_name, const std::vector<ServiceInstance>& instances);

            /**
             * @brief 加权轮询策略选择实例
             * @param service_name 服务名称
             * @param instances 健康实例列表
             * @return 选中的实例
             */
            std::optional<ServiceInstance> selectWeightedRoundRobin(
                const std::string& service_name, const std::vector<ServiceInstance>& instances);

            /**
             * @brief 最少连接数策略选择实例
             * @param service_name 服务名称
             * @param instances 健康实例列表
             * @return 选中的实例
             */
            std::optional<ServiceInstance> selectLeastConnections(
                const std::string& service_name, const std::vector<ServiceInstance>& instances);

            /**
             * @brief 将策略枚举转换为字符串
             * @param strategy 负载均衡策略
             * @return 策略名称字符串
             */
            static std::string strategyToString(Strategy strategy);
        };

    }
}




#endif //LOAD_BALANCER_H
